//
// Database.m
// Copyright (c) 1990 by Jiro Nakamura 
// All rights reserved
//
//
// RCS Information
// Revision Number->	$Revision: 2.3 $
// Last Revised->	$Date: 90/02/03 13:01:44 $
//
static char rcsid[] = "$Header: /user/jiro/Programming/Cassandra/src/RCS/Event.m,v 2.3 90/02/03 13:01:44 jiro Exp $";

#import "Database.h"
#import <objc/objc.h>
#import <strings.h>
#import <appkit/Panel.h>       /* for NXRunAlertPanel */
#import <appkit/Cursor.h>	// For NXWait
#import "misc.h"


@implementation Database 

+ new
{
#ifdef DEBUG
	fprintf(stderr,"Database.m:New\n");
#endif

	self = [super new];
	[self setDefaults];
	return self;
}

+ newAt: (char *) filename;
{
#ifdef DEBUG
	fprintf(stderr,"Database.m:NewAt %s\n", filename);
#endif

	self = [super new];
	present = next = previous = -1;
	recordLength = 512;

	strcpy(dataFile, filename);
	return self;
}


- free
{
#ifdef DEBUG
	fprintf(stderr,"Database.m:Free ->Closing event!\n");
#endif
	[super free];
	return nil;
}


- setDefaults
{
	present = next = previous = -1;
	strcpy(dataFile, "-- File undefined --");
	recordLength = 512;
	return self;
}


- (int) readRecord: (RecordPointer) here	/* read record from data file */
{
	FILE * source;
	static char errormsg[128], buf[512];
	char *sPointer;
		
	#ifdef DEBUG
		fprintf(stderr,	"------------------------\n"
				"[Database readRecord: %d]\n",here);
	#endif
	

	if( here < 0)
		return ILLEGAL_RECORD_NUMBER;

	sprintf(errormsg, "Fatal error occured while trying to read database %s", dataFile);
	source = fileOpen(dataFile, "r+",errormsg);

	sprintf(errormsg, "An fatal error occured when we were trying to seek to record #%d in database %s.\n This program will crash.", here, dataFile);
	if( fileSeek(source, here, errormsg) == NULL)
		{
		present = here;
		return SEEK_ERROR;
		}

	for(;;)	
		{
		if( fgets( buf,512, source) == NULL)
			break;
		
		if(strcmp(buf,"Finish.") == 0)
			break;
		
		fprintf(stderr,"Buffer is %s.\n", buf);
		
		sPointer = index(buf,':') + 1;
		*(sPointer - 1) = '\0';		
		fprintf(stderr, 
			"Buffer is now %s, sPointer is %s\n",buf,sPointer);
	/*	[self @selector(buf2) with: value]; */
		}
	
	
	fclose(source);
	return NO_ERROR;
}
				
- (int) firstRecord
{
	#ifdef DEBUG
		fprintf(stderr,"Reading the first record.\n");
	#endif

	[self readRecord : 0];
	if( [self next] == 0)
		return END_OF_RECORDS;
	[self readRecord : [self next]];
	return NO_ERROR;
}	
	
- (int) writeRecord : (RecordPointer) here	
/* write itself into the database using present as its index */
{
	FILE *source;
	char errormsg[256];
		
	if( here < 0)
		return ILLEGAL_RECORD_NUMBER;
		
	#ifdef DEBUG
		fprintf(stderr,	"------------------------\n"
				"[Database writeRecord: %d]: Opening event with <%s>!\n",here, dataFile);
	#endif

	sprintf(errormsg, "Fatal error when trying to write to database %s", dataFile);
	source = fileOpen(dataFile, "r+",errormsg);
	
	sprintf(errormsg, "An fatal error occured when we were trying to seek to record #%d for writing in database %s.\n This program has crashed.", here, dataFile);
	fileSeek(source, here, errormsg);
	
	present = here;
	
	fclose(source);
	return NO_ERROR;
}

- (RecordPointer) insertRecord
{
	return [self insertRecordFrom : 1];
}



/* insert itself into the file with method indexCompare:with: as indexer */
/* and starting from <here> in searching for a open deleted space */
- (RecordPointer) insertRecordFrom : (RecordPointer) here
{
	id presentRecord, stepRecord;
	int loop;
	
	// This may take a while, so use the system wait cursor
	[NXWait push];

	presentRecord = [[self class] newAt: dataFile];
	stepRecord = [[self class] newAt: dataFile];
	
	[presentRecord readRecord:0];
	for( [presentRecord readRecord: [presentRecord next]]; 
	      [presentRecord present] != 0 && [self indexCompare: presentRecord with:self] < 1;
	      [presentRecord readRecord: [presentRecord next]])
	      	{
	      	#ifdef DEBUG
			fprintf(stderr, "From %d looping onto %d\n",[presentRecord present],[presentRecord next]);
		#endif
		}
	#ifdef DEBUG	
		fprintf(stderr, "inserting between %d <- event -> %d.\n",[presentRecord previous], [presentRecord present]);
	#endif
	
	previous = [presentRecord previous];
	next = [presentRecord present];
	
	[stepRecord setNext: 0];
	for( loop = here; !([stepRecord next] == -1 && [stepRecord previous] == -1);
		[stepRecord readRecord: loop++])
		{
		#ifdef DEBUG
			fprintf(stderr, "reading at %d.\n",loop);
		#endif
		}
		
	present = [stepRecord present];
	
	[self writeRecord: present];
	
	[stepRecord readRecord: previous];
	[stepRecord setNext : present];
	[stepRecord writeRecord:previous];
	
	[stepRecord readRecord: next];
	[stepRecord setPrevious : present];
	[stepRecord writeRecord:next];
	
	[stepRecord free];
	[presentRecord free];
	#ifdef DEBUG
		fprintf(stderr,"successfully inserted %d <- %d -> %d\n\n",[self previous],[self present], [self next]);
	#endif


	// Finished, restore the cursor
	NXPing();
	[NXWait pop];
	
	return( [self present] );
}

- deleteRecord: (RecordPointer) here		/* delete itself from the file with present as index */
{
	id previousRecord, nextRecord;
	
	#ifdef DEBUG
		fprintf(stderr, "Deleting <%d>\n\n",here);
	#endif
	
	if( here <= 0)
		{
			NXRunAlertPanel(NULL,"You cannot delete link 0 or below. OK?", "Shucks...",NULL,NULL);
			fprintf(stderr,"Can't delete the flipping header, ok!  Here = %d.\n\n",here);
			return nil;
		}
	
	previousRecord= [[self class] newAt: dataFile];
	nextRecord = [[self class] newAt: dataFile];
	
	[previousRecord readRecord  :here];
	if( ( [previousRecord previous] == -1  )   ||  (  [previousRecord next]  == -1  ))
		return nil;
	
	[nextRecord readRecord :[previousRecord next]];				/* Set the previous_link of the next link */
	[nextRecord setPrevious  : [previousRecord previous]];			/* to the one of the previous one */
	[nextRecord writeRecord  :[previousRecord next]];				/* confusing, eh? */
	
	[nextRecord readRecord  :[previousRecord previous] ];	
	/* do the same confusing spiel for previous */
	[nextRecord setNext  : [previousRecord next]];
	[nextRecord writeRecord  :[previousRecord previous] ];
	
	[previousRecord setNext  : -1];	/* cancel out the header to finally kill it */
	[previousRecord setPrevious  :-1];	
	[previousRecord writeRecord  :here];	/* and write it out */
	
	#ifdef DEBUG
		fprintf(stderr, "Record %d successfully deleted, O Leader.\n\n",here);
	#endif
	
	[previousRecord free];
	[nextRecord free];
	return self;
}


- (int) indexCompare: (id) first  with: (id) second
{
	return 0;
}




- (RecordPointer) present
{
	return present;
}

- (RecordPointer) previous
{
	return previous;
}

- (RecordPointer) next
{
	return next;
}

- setPresent : (RecordPointer) apresent
{
	present = apresent;
	return self;
}
- setPrevious  : (RecordPointer) aprevious
{
	previous =aprevious;
	return self;
}

- setNext  : (RecordPointer) anext
{
	next = anext;
	return self;
}

- (char *) dataFile;
{
	return dataFile;
}

- setDataFile: (char *) filename
{
	strcpy(dataFile, filename);
	return self;
}
@end		


